package net.dopan.pigframe.gateway.component.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import net.dopan.pigframe.core.utils.SecurityConstants;
import net.dopan.pigframe.gateway.util.RibbonVersionHolder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER;

/**
 * @Package:  net.dopan.pigframe.gateway.component.filter
 * @Title: AccessFilter
 * @Description: 在RateLimitPreFilter 之前执行，不然又空指针问题
 * @author: 刘宽
 * @date: 2018/9/2 17:10
 */
@Slf4j
@Component
public class AccessFilter extends ZuulFilter {

    @Value("${zuul.ribbon.metadata.enabled:false}")
 	private boolean canary;

    @Override
    public String filterType() {
        // 过滤器的类型，它决定过滤器在请求的哪个生命周期中执行。这里定义为pre，代表会在请求被路由之前执行。另外还有“route”、“post”、"error”等类型
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        // int值来定义过滤器的执行顺序，数值越小优先级越高
        return FORM_BODY_WRAPPER_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        // 判断该过滤器是否需要被执行。这里我们直接返回true,因此该过滤器对所有请求都会生效,实际运用中我们可以利用该函数来指定过滤器的有效范围
        return true;
    }

    @Override
    public Object run() {
        // 过滤器的具体逻辑
        RequestContext requestContext = RequestContext.getCurrentContext();
        String version = requestContext.getRequest().getHeader(SecurityConstants.VERSION);
        if (canary && StrUtil.isNotBlank(version)) {
            RibbonVersionHolder.setContext(version);
        }
        requestContext.set("startTime", System.currentTimeMillis());

        HttpServletRequest request = requestContext.getRequest();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        log.info("send {} request to {}, authentication:{}", request.getMethod(), request.getRequestURL().toString(), authentication);
        if (authentication != null) {
            requestContext.addZuulRequestHeader(SecurityConstants.USER_HEADER, authentication.getName());
            requestContext.addZuulRequestHeader(SecurityConstants.ROLE_HEADER, CollectionUtil.join(authentication.getAuthorities(), ","));
        }
        return null;
    }

}
